package com.ruoyi.web.controller.project;

import java.time.LocalDate;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.math.NumberUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.AESECBPKCS5Util;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.util.ShiroUtils;
import com.ruoyi.project.domain.ConContract;
import com.ruoyi.project.domain.ConProcess;
import com.ruoyi.project.domain.ProProject;
import com.ruoyi.project.domain.ProProjectContract;
import com.ruoyi.project.service.IConContractService;
import com.ruoyi.project.service.IConProcessService;
import com.ruoyi.project.service.IProProjectContractService;
import com.ruoyi.project.service.IProProjectService;
import com.ruoyi.system.domain.SysDept;
import com.ruoyi.system.service.ISysDeptService;

/**
 * 合同Controller
 * 
 * @author phil
 * @date 2020-05-29
 */
@Controller
@RequestMapping("/project/contract")
public class ConContractController extends BaseController{
	private String prefix = "project/contract";

	@Autowired
	private IConContractService conContractService;

	@Autowired
	private IProProjectService proProjectService;

	@Autowired
	private ISysDeptService deptService;

	@Autowired
	IProProjectContractService proProjectContractService;

	@Autowired
	private IConProcessService conProcessService;

	@RequiresPermissions("project:contract:view")
	@GetMapping()
	public String contract(){
		return prefix + "/contract";
	}

	/**
	 * 查询合同列表
	 */
	@RequiresPermissions("project:contract:list")
	@PostMapping("/list")
	@ResponseBody
	public TableDataInfo list(ConContract conContract){
		startPage();
		List<ConContract> list = conContractService.selectConContractList(conContract);
		return getDataTable(list);
	}

	/**
	 * 导出合同列表
	 */
	@RequiresPermissions("project:contract:export")
	@Log(title = "合同", businessType = BusinessType.EXPORT)
	@PostMapping("/export")
	@ResponseBody
	public AjaxResult export(ConContract conContract){
		List<ConContract> list = conContractService.selectConContractList(conContract);
		ExcelUtil<ConContract> util = new ExcelUtil<ConContract>(ConContract.class);
		return util.exportExcel(list, "contract");
	}

	/**
	 * 下载导入模板
	 * 
	 * @return
	 */
	@RequiresPermissions("project:contract:importTemplate")
	@GetMapping("/importTemplate")
	@ResponseBody
	public AjaxResult importTemplate(){
		ExcelUtil<ConContract> util = new ExcelUtil<ConContract>(ConContract.class);
		return util.importTemplateExcel("合同数据");
	}

	/**
	 * 导入合同
	 * 
	 * @param file
	 * @param updateSupport
	 * @return
	 * @throws Exception
	 */
	@RequiresPermissions("project:contract:import")
	@PostMapping("/importData")
	@ResponseBody
	public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception{
		ExcelUtil<ConContract> util = new ExcelUtil<ConContract>(ConContract.class);
		List<ConContract> contractList = util.importExcel(file.getInputStream());
		// 格式校验
		String operName = ShiroUtils.getSysUser().getLoginName();
		String message = importContract(contractList, updateSupport, operName);
		return AjaxResult.success(message);
	}

	/**
	 * 导入合同
	 * 
	 * @param contractList
	 * @param isUpdateSupport
	 * @param operName
	 * @return
	 */
	public String importContract(List<ConContract> contractList, boolean isUpdateSupport, String operName) throws Exception{
		if(StringUtils.isNull(contractList) || contractList.size() == 0){
			throw new BusinessException("导入数据不能为空！");
		}

		// 查询系统单位
		SysDept dept = new SysDept();
		dept.setStatus("0");
		List<SysDept> deptList = deptService.selectDeptList(dept);

		// 查询项目列表
		ProProject project = new ProProject();
		List<ProProject> projectList = proProjectService.selectProProjectList(project);

		// 查询合同列表
		ConContract oldContract = new ConContract();
		List<ConContract> oldContractList = conContractService.selectConContractList(oldContract);

		int failureNum = 0; // 错误数
		int rowNum = 1; // 起始行数
		StringBuilder successMsg = new StringBuilder();
		StringBuilder failureMsg = new StringBuilder();

		// 遍历校验
		for(ConContract contract : contractList){
			++rowNum;
			// 合同编号
			String contractNo = contract.getContractNo();
			if(StringUtils.isEmpty(contractNo)){
				failureNum++;
				failureMsg.append("<br/>" + failureNum + "、第" + rowNum + "行，合同编号不允许为空");
			}else{
				boolean hasFlag = checkHasContractNo(contractNo, oldContractList);
				if(hasFlag){
					failureNum++;
					failureMsg.append("<br/>" + failureNum + "、第" + rowNum + "行，合同编号在系统已存在");
				}
			}

			// 合同名称
			String contractName = contract.getContractName();
			if(StringUtils.isEmpty(contractName)){
				failureNum++;
				failureMsg.append("<br/>" + failureNum + "、第" + rowNum + "行，合同名称不允许为空");
			}

			// 合同类型
			String contractType = contract.getContractType();
			if(StringUtils.isEmpty(contractType)){
				failureNum++;
				failureMsg.append("<br/>" + failureNum + "、第" + rowNum + "行，合同类型不允许为空");
			}else{
				int flag = NumberUtils.toInt(contractType, -1);
				if(flag == -1){
					failureNum++;
					failureMsg.append("<br/>" + failureNum + "、第" + rowNum + "行，合同类型:" + contractType + "在码表不存在");
				}
			}

			// 所属业务部门转换
			String deptNames = contract.getDeptNames();
			if(StringUtils.isEmpty(deptNames)){
				failureNum++;
				failureMsg.append("<br/>" + failureNum + "、第" + rowNum + "行，所属业务部门不允许为空");
			}
			String deptIds = "";
			deptNames = deptNames.replace("，", ",");
			String[] deptNameArray = deptNames.split(",");
			if(deptNameArray != null && deptNameArray.length > 0){
				for(int i = 0; i < deptNameArray.length; i++){
					Long deptId = selectDeptIdByName(deptNameArray[i], deptList);
					if(deptId == null){
						failureNum++;
						failureMsg.append("<br/>" + failureNum + "、第" + rowNum + "行，" + deptNameArray[i] + "，部门在系统内未找到");
					}else{
						deptIds += deptId + ",";
					}
				}
				if(!"".equals(deptIds)){
					deptIds = deptIds.substring(0, deptIds.length() - 1);
					contract.setDeptIds(deptIds);
				}
			}

			// 项目转换
			String projectNOs = contract.getProjectNOs();
			if(StringUtils.isEmpty(projectNOs)){
				failureNum++;
				failureMsg.append("<br/>" + failureNum + "、第" + rowNum + "行，项目编码不允许为空");
			}else{
				String projectIds = "";
				projectNOs = projectNOs.replace("，", ",");
				String[] projectNoArray = projectNOs.split(",");
				if(projectNoArray != null && projectNoArray.length > 0){
					for(String no : projectNoArray){
						Long projectId = selectProjectIdByNo(no, projectList);
						if(projectId == null){
							failureNum++;
							failureMsg.append("<br/>" + failureNum + "、第" + rowNum + "行，" + no + "，项目编码在系统不存在");
						}else{
							projectIds += projectId + ",";
						}
					}
					if(!"".equals(projectIds)){
						projectIds = projectIds.substring(0, projectIds.length() - 1);
						contract.setProjectIds(projectIds);
					}
				}
			}

			// 合同金额
			String amount = contract.getAmount();
			if(StringUtils.isNotEmpty(amount)){
				contract.setAmount(AESECBPKCS5Util.encrypt(amount));
			}
			// 合同开票金额
			String invoicedAmount = contract.getInvoicedAmount();
			if(StringUtils.isNotEmpty(invoicedAmount)){
				contract.setInvoicedAmount(AESECBPKCS5Util.encrypt(invoicedAmount));
			}
			// 合同总到款额
			String receivedAmount = contract.getReceivedAmount();
			if(StringUtils.isNotEmpty(receivedAmount)){
				contract.setReceivedAmount(AESECBPKCS5Util.encrypt(receivedAmount));
			}

			contract.setCreateTime(new Date());
			contract.setCreateBy(operName);
		}
		if(failureNum > 0){
			failureMsg.insert(0, "很抱歉，系统检测出来错误！共 " + failureNum + " 处数据格式不正确，错误如下：");
			throw new BusinessException(failureMsg.toString());
		}else{
			int successNum = conContractService.insertConContracts(contractList);
			successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
		}
		return successMsg.toString();
	}

	/**
	 * 根据项目编码查询项目ID
	 * 
	 * @param projectNO
	 * @param projectList
	 * @return
	 */
	private Long selectProjectIdByNo(String projectNO, List<ProProject> projectList){
		Long projectId = null;
		if(projectList != null && projectList.size() > 0 && projectNO != null && !"".equals(projectNO)){
			for(ProProject project : projectList){
				if(projectNO.trim().equals(project.getProjectNo())){
					projectId = project.getProjectId();
					break;
				}
			}
		}
		return projectId;
	}

	/**
	 * 判断合同编号在系统是否已存在
	 * 
	 * @param contractNo
	 * @param oldContractList
	 * @return
	 */
	private boolean checkHasContractNo(String contractNo, List<ConContract> oldContractList){
		boolean hasFlag = false;
		if(oldContractList != null && oldContractList.size() > 0 && contractNo != null && !"".equals(contractNo)){
			for(ConContract contract : oldContractList){
				if(contractNo.trim().equals(contract.getContractNo())){
					hasFlag = true;
					break;
				}
			}
		}
		return hasFlag;
	}

	/**
	 * 通过手机号核对pmId
	 * 
	 * @return
	 */
	public Long selectDeptIdByName(String deptName, List<SysDept> deptList){
		Long deptId = null;
		if(deptList != null && deptList.size() > 0){
			for(SysDept dept : deptList){
				if(deptName.trim().equals(dept.getDeptName())){
					deptId = dept.getDeptId();
					break;
				}
			}
		}
		return deptId;
	}

	/**
	 * 新增合同
	 */
	@GetMapping("/add")
	public String add(ModelMap mmap){
		LocalDate date = LocalDate.now();
		int currentYear = date.getYear();
		mmap.addAttribute("currentYear", currentYear);
		return prefix + "/add";
	}

	/**
	 * 新增保存合同
	 */
	@RequiresPermissions("project:contract:add")
	@Log(title = "合同", businessType = BusinessType.INSERT)
	@PostMapping("/add")
	@ResponseBody
	public AjaxResult addSave(ConContract conContract) throws Exception{
		// 合同金额
		String amount = conContract.getAmount();
		if(StringUtils.isNotEmpty(amount)){
			conContract.setAmount(AESECBPKCS5Util.encrypt(amount));
		}
		// 合同开票金额
		String invoicedAmount = conContract.getInvoicedAmount();
		if(StringUtils.isNotEmpty(invoicedAmount)){
			conContract.setInvoicedAmount(AESECBPKCS5Util.encrypt(invoicedAmount));
		}
		// 合同总到款额
		String receivedAmount = conContract.getReceivedAmount();
		if(StringUtils.isNotEmpty(receivedAmount)){
			conContract.setReceivedAmount(AESECBPKCS5Util.encrypt(receivedAmount));
		}
		return toAjax(conContractService.insertConContract(conContract));
	}

	/**
	 * 修改合同
	 */
	@GetMapping("/edit/{contractId}")
	public String edit(@PathVariable("contractId") Long contractId, ModelMap mmap){
		ConContract conContract = conContractService.selectConContractById(contractId);
		mmap.put("conContract", conContract);
		return prefix + "/edit";
	}

	/**
	 * 修改保存合同
	 */
	@RequiresPermissions("project:contract:edit")
	@Log(title = "合同", businessType = BusinessType.UPDATE)
	@PostMapping("/edit")
	@ResponseBody
	public AjaxResult editSave(ConContract conContract){
		return toAjax(conContractService.updateConContract(conContract));
	}

	/**
	 * 删除合同
	 */
	@RequiresPermissions("project:contract:remove")
	@Log(title = "合同", businessType = BusinessType.DELETE)
	@PostMapping("/remove")
	@ResponseBody
	@Transactional
	public AjaxResult remove(String ids){
		int successNum = 0;
		if(ids != null && !"".equals(ids)){
			String[] idsArray = Convert.toStrArray(ids);
			for(String conId : idsArray){
				// 判断当前合同是否有里程碑，如果有,不允许删除
				ConProcess oldConProcess = new ConProcess();
				oldConProcess.setConId(NumberUtils.toLong(conId));
				List<ConProcess> ConProcessList = conProcessService.selectConProcessList(oldConProcess);
				if(ConProcessList != null && ConProcessList.size() > 0){
					throw new BusinessException("选中合同包含里程碑信息，无法进行删除");
				}

				// 删除合同与项目之前的关系
				Long contractId = NumberUtils.toLong(conId);
				ProProjectContract pc = new ProProjectContract();
				pc.setConId(contractId);
				proProjectContractService.deleteProProjectContract(pc);

				// 删除合同
				successNum = conContractService.deleteConContractById(contractId);
			}
		}
		return toAjax(successNum);
	}
}
